package com.tencent.txcc.service.impl;

import com.tencent.txcc.constants.Constants;
import com.tencent.txcc.domain.Blacklist;
import com.tencent.txcc.domain.MessageSms;
import com.tencent.txcc.dto.BlackListDto;
import com.tencent.txcc.dto.SmsCodeDto;
import com.tencent.txcc.dto.SmsRedisDto;
import com.tencent.txcc.enums.GlobleExceptionCode;
import com.tencent.txcc.exception.BusinessException;
import com.tencent.txcc.mapper.BlacklistMapper;
import com.tencent.txcc.properties.SmsRegisterProperties;
import com.tencent.txcc.service.IMessageSmsService;
import com.tencent.txcc.service.IVerifyCodeService;
import com.tencent.txcc.util.AssertUtil;
import com.tencent.txcc.utils.StrUtils;
import com.tencent.txcc.utils.VerifyCodeUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class VerifyCodeServiceImpl implements IVerifyCodeService {

    @Autowired
   private RedisTemplate<Object,Object> redisTemplate;

    @Autowired
    private IMessageSmsService messageSmsService;

    @Autowired
    private SmsRegisterProperties smsRegisterProperties;

    @Autowired
    private BlacklistMapper blacklistMapper;

    @Override
    public String image(String key) {
        // 调用工具类生成图形吗
        String code = StrUtils.getComplexRandomString(4);
        // 保存到redis                  （设键名，传入的图形码， 持续时间5分钟）
        redisTemplate.opsForValue().set(key,code,5, TimeUnit.MINUTES);
        //使用工具类生成图形验证码编码之后的base64的字符串    （图形的宽，高，内容）
        String base64Str = VerifyCodeUtils.verifyCode(110, 40, code);
        return base64Str;
    }

    @Override
    public void sendSmsCode(SmsCodeDto smsCodeDto) {
        String imageCode = smsCodeDto.getImageCode();
        Date date = new Date();

        // 断言imageCode不为空，如果为空的话就执行GlobleExceptionCode.PARAM_IS_NULL
        AssertUtil.isNotNull(imageCode, GlobleExceptionCode.PARAM_IS_NULL);
//        if (imageCode.isEmpty()){
//            throw new BusinessException(GlobleExceptionCode.IMAGECODE_IS_NULL);
//        }


        // 断言手机号码不为空，为空的话就执行GlobleExceptionCode.PHONENUMBER_IS_NUM
        AssertUtil.isNotNull(smsCodeDto.getPhone(), GlobleExceptionCode.PHONENUMBER_IS_NUM);
//        if (smsCodeDto.getPhone() == null){
//            throw new BusinessException(GlobleExceptionCode.PHONENUMBER_IS_NUM);
//        }


        // 在redis中寻找有没有图形验证码的key值
        String key = smsCodeDto.getImageCodeKey();
        Object o = redisTemplate.opsForValue().get(key);

        // 断言图形验证码为空，如果为空则说明图形验证码过期了
        AssertUtil.isNotNull(o, GlobleExceptionCode.IMAGECODE_IS_OUT_OF_TIME);
//        if (o == null){
//            throw new BusinessException(GlobleExceptionCode.IMAGECODE_IS_OUT_OF_TIME);
//        }

        // 断言前端传入的图形验证码和redis中的图形验证码一样，如果不一样则说明图形验证码出错
        AssertUtil.isEqualsIgnoreCase(o.toString(), imageCode, GlobleExceptionCode.IMAGECODE_IS_NOT_OK);
//        if(!o.toString().equalsIgnoreCase(imageCode)){
//            throw new BusinessException(GlobleExceptionCode.IMAGECODE_IS_NOT_OK);
//        }

        // 获取前端传入的手机号
        String phone = smsCodeDto.getPhone();

        // 优化 魔法值
        String redisKey = String.format(Constants.REDIS_PHONE_CONSTANTS, phone);

        // 获取redis中的手机短信验证码
        Object obj  = redisTemplate.opsForValue().get(redisKey);

        //
        String smsCode = null;
        // 如果手机验证码过期了，或者是还没有生成过

        if (obj != null){
            // 获取redis中验证码时间戳
            // Long aLong = Long.valueOf(codeObj.toString().split(":")[1]);
            SmsRedisDto smsValueDto = (SmsRedisDto)obj;

            // 断言现在的时间戳减去redis中的时间戳小于一分钟，执行GlobleExceptionCode.FREQUENT_OPERATE
            AssertUtil.isTrue(date.getTime() - smsValueDto.getTime() < smsRegisterProperties.getIntervaltime(), GlobleExceptionCode.FREQUENT_OPERATE);
//            if (date.getTime() - aLong < 60000){
//                throw new BusinessException(GlobleExceptionCode.FREQUENT_OPERATE);
//            }

            if(smsRegisterProperties.getExpirationtime() > date.getTime() - smsValueDto.getTime() && date.getTime() - smsValueDto.getTime() > smsRegisterProperties.getIntervaltime()){
                // 获取出redis中的验证码
//                String redisCode = codeObj .toString().split(":")[0];
                // 优化
                // 将redis中的验证码重新发送
                smsCode = smsValueDto.getCode();
            }
        } else {
            BlackListDto blackListDto = new BlackListDto();
            blackListDto.setPhone(smsCodeDto.getPhone());
            Blacklist blackUser = blacklistMapper.findBlackUser(blackListDto);
//            if (blackUser == null){
//                smsCode = StrUtils.getRandomString(smsRegisterProperties.getSmscodesize());
//            } else {
            AssertUtil.isNull(blackUser, GlobleExceptionCode.BLACKLIST_IS_NOT_EMPTY);
            smsCode = StrUtils.getRandomString(smsRegisterProperties.getSmscodesize());
//            }



        }
        SmsRedisDto smsRedis = new SmsRedisDto(smsCode, date.getTime());
        // 将获得的smscode保存在redis中
        // redisTemplate.opsForValue().set("register:" + phone, smsRedisDto.getCode() + ":" + smsRedisDto.getTime(), this.smsRegisterProperties.getExpirationtime(), TimeUnit.MILLISECONDS);
        // redisTemplate.opsForValue().set(redisKey , smsRedis, smsRegisterProperties.getExpirationtime(), TimeUnit.MILLISECONDS);
        redisTemplate.opsForValue().set( redisKey, smsRedis, smsRegisterProperties.getExpirationtime(), TimeUnit.MILLISECONDS);
        log.info(smsCode);

        sendMessage(date, smsCode);

    }

    private void sendMessage(Date date, String smsCode) {
        MessageSms messageSms = new MessageSms();
        // "您的验证码为: %s，请在5分钟之内填写"将占位符转为smsCode
        String content = String.format(smsRegisterProperties.getContent(), smsCode);
        messageSms.setTitle(smsRegisterProperties.getTitle());
        messageSms.setContent(content);
        messageSms.setSendTime(date);
        messageSmsService.insert(messageSms);
        log.info(content);
    }


}
